//
//  UMDFileReader.m
//  UMDReader
//
//  Created by 张 霄鹤 on 10-1-6.
//  Copyright 2010 xhzhang. All rights reserved.
//


#import "zlib.h"

#import "UMDFileReader.h"

#import "Chapter.h"


@implementation UMDFileReader

- (id)init{
	if(self = [super init]){
		chaptersOffset = [[NSMutableArray alloc] init];
		zippedContentList = [[NSMutableArray alloc] init];
		totalImageList = [[NSMutableArray alloc] init];		
	}
	return self;
}

- (UMDBook *)read:(NSString *)filePath{
	UMDBook *ret = nil;
	if(filePath){
		
		//NSString *docPath = [self applicationDocumentsDirectory];
		//NSString *fs = [[NSBundle mainBundle] pathForResource:filePath ofType:@"umd"];
		//NSLog(docPath);
		//NSString *fs = [NSString stringWithFormat:@"%@/%@",docPath,filePath];
		
		// TODO 以下是通过 NSData 来获取文件所有内容的方式
		NSData *data = [NSData dataWithContentsOfFile:filePath];
		if(data){
			LEDataInputStream *din = [[LEDataInputStream alloc] initWithData:data];
			ret = [self readWithInputStream:din];
			[din release];
		}
	}
	return ret;
}

- (UMDBook *)readWithInputStream:(LEDataInputStream *)din{
	NSInteger ivalue = [din readInt];
	UMDBook *ret = [[UMDBook alloc] init];
	if(ivalue == 0xde9a9b89){
		// NSLog(@"UMD File Magic is OK");
		char value = [din read];
		short num2 = -1;
		while(value == '#'){
			short segType = [din readShort];
			char  segFlag = [din read];
			char  length = [din read] - 5;
			[self readSection:segType withFlag:segFlag andLength:length useStream:din forBook:ret];
			if ((segType == 0xf1) || (segType == 10)) {
                segType = num2;
            }
            num2 = segType;
			
			value = [din read];
            while (value == '$') {
                int addCheckNumber = [din readInt];
                int num7 = [din readInt] - 9;
                [self readAdditionalSection:segType withCheckNum:addCheckNumber andLength:num7 useStream:din forBook:ret];
                value = [din read];
            }
		}
	}
	
	if (ret.bookType == 1) {
		[self parseChapterTextContents:ret];
	} else {
		if (ret.bookType == 2) {
			[self parseChapterImages:ret];
		}
	}
	
	return [ret autorelease];
}

- (void)readSection:(short)segType withFlag:(char)flag andLength:(char)length useStream:(LEDataInputStream *)reader forBook:(UMDBook *)bk{
	short num1 = segType;
	char *buf;
	switch (num1) {
		case 1: {
			bk.bookType = [reader read];
			// bk.bookType[1] = bk.bookType[0];
			[reader readShort];
			return;
		}
		case 2: {
			// char chs[length];
			// buf = chs;
			// [reader readBytes:buf withLength:length];
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			bk.bookTitle = [[[NSString alloc] initWithBytes:buf length:len encoding:NSUTF16LittleEndianStringEncoding] autorelease];
			return;
		}
		case 3: {
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			bk.bookAuth = [[[NSString alloc] initWithBytes:buf length:len encoding:NSUTF16LittleEndianStringEncoding] autorelease];
			return;
		}
		case 4: {
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			publishYear = [[[NSString alloc] initWithBytes:buf length:len encoding:NSUTF16LittleEndianStringEncoding] autorelease];
			return;
		}
		case 5: {
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			publishMonth = [[[NSString alloc] initWithBytes:buf length:len encoding:NSUTF16LittleEndianStringEncoding] autorelease];
			return;
		}
		case 6: {
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			publishDay = [[[NSString alloc] initWithBytes:buf length:len encoding:NSUTF16LittleEndianStringEncoding] autorelease];
			return;
		}
		case 7: {
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			bk.bookKind = [[[NSString alloc] initWithBytes:buf length:len encoding:NSUTF16LittleEndianStringEncoding] autorelease];
			return;
		}
		case 8: {
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			bk.bookPublisher = [[[NSString alloc] initWithBytes:buf length:len encoding:NSUTF16LittleEndianStringEncoding] autorelease];
			return;
		}
		case 9: {
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			bk.bookVendor = [[[NSString alloc] initWithBytes:buf length:len encoding:NSUTF16LittleEndianStringEncoding] autorelease];
			return;
		}
		case 10: {
			[reader readInt];
			return;
		}
		case 11: {
			totalContentLength = [reader readInt];
			return;
		}
		case 12: {
			[reader readInt];
			return;
		}
		case 13: {
			[reader readInt];
			return;
		}
		case 14: {
			[reader read];
			return;
		}
		case 15: {
			[reader skip:length];
			bk.bookType = 3;
			return;
		}
		case 17: {
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			bk.buyer = [[[NSString alloc] initWithBytes:buf length:len encoding:NSUTF16LittleEndianStringEncoding] autorelease];
			return;
		}
		case 18:{
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			bk.sign = [[[NSString alloc] initWithBytes:buf length:len encoding:NSUTF16LittleEndianStringEncoding] autorelease];
			return;
		}

	}
	switch (num1) {
		case 0x81:
		case 0x83:
		case 0x84: {
			additionalCheckNumber = [reader readInt];
			return;
		}
		case 0x82: {
			[reader read];
			additionalCheckNumber = [reader readInt];
			return;
		}
	}
	[reader skip:length];

}

- (void)readAdditionalSection:(short)segType
				 withCheckNum:(NSInteger)checkNumber
					andLength:(NSInteger)length
					useStream:(LEDataInputStream *)reader
					  forBook:(UMDBook *)bk{
	
	// TODO read
	
	char *buf;
	switch (segType) {
		case 14: {
			//char chs[length];
//			buf = chs;
//			[reader readBytes:buf withLength:length];
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			// TODO 将 buf 创建成为 Data或者UIImage进行存储
			NSData *d = [NSData dataWithBytesNoCopy:buf length:len];
			[totalImageList addObject:d];
			return;
		}
		case 15: {
			//char chs[length];
//			buf = chs;
//			[reader readBytes:buf withLength:length];
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			// TODO 将 buf 创建成为 Data或者UIImage进行存储
			NSData *d = [NSData dataWithBytesNoCopy:buf length:len];
			[totalImageList addObject:d];
			return;
		}
		case 0x81:
			[reader skip:length];
			return;
			
		case 0x82:{
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			// TODO 将 buf 创建成为 Data或者UIImage进行存储
			NSData *d = [NSData dataWithBytesNoCopy:buf length:len];
			UIImage *image = [UIImage imageWithData:d];
			bk.bookCover = image;
			return;
		}
		case 0x83:
			[chaptersOffset removeAllObjects];
			int cc = length / 4;
			for (int i = 0; i < cc; i++) {
				NSString *off = [NSString stringWithFormat:@"%d",[reader readInt]];
				[chaptersOffset addObject:off];
			}
			return;
			
		case 0x84:
			if (additionalCheckNumber == checkNumber) {
				int index = 0;
				NSInteger len = 0;
				buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
				while (index < len) {
					char count = buf[index];
					index++;
					// NSData *d = [NSData dataWithBytes:buf length:len];
					char *cs = &buf[index];
					// [d getBytes:cs range:(NSMakeRange(index, count))];
					NSString *t = [[[NSString alloc] initWithBytes:cs length:count encoding:NSUTF16LittleEndianStringEncoding] autorelease];
					[bk.bookChapters addObject:[[[Chapter alloc]initWithTitle:t andContent:@""] autorelease]];
					index += count;
				}
				return;
			}
			NSInteger len = 0;
			buf = [reader getCurrentBytesRefwithLength:length retLength:&len];
			// NSData *dt = [NSData dataWithBytes:buf length:len];
			NSData *dt = [NSData dataWithBytesNoCopy:buf length:len];
			[zippedContentList addObject:dt];
			return;
	}
	[reader skip:length];

}

- (void)parseChapterImages:(UMDBook *)bk{
	int num1 = 0;
	int count = [bk.bookChapters count];
	for (int i = 0; i < count; i++) {
		NSString *st;
		if (i < (count - 1)) {
			st = (NSString *)[chaptersOffset objectAtIndex:(i + 1)];
			num1 = [st intValue];
		} else {
			num1 = [totalImageList count];
		}
		st = [chaptersOffset objectAtIndex:i];
		int num5 = [st intValue];
		for (int j = num5; j < num1; j++) {
			Chapter *ch = (Chapter *)[bk.bookChapters objectAtIndex:i];
			[ch appendImage:(UIImage *)[totalImageList objectAtIndex:j]];
		}
	}
	if (num1 < [totalImageList count]) {
		Chapter *chapter = [[[Chapter alloc] initWithTitle:@"\u672a\u77e5" andContent:@""] autorelease];
		for (int z = num1; z < [totalImageList count]; z++) {
			[chapter appendImage:(UIImage *)[totalImageList objectAtIndex:z]];
		}
		[bk appendChapter:chapter];
	}
	[totalImageList removeAllObjects];
}

/**
 * 解析文章内容，对于优化来说，可以在阅读的时候进行解析
 */
- (void)parseChapterTextContents:(UMDBook *)bk{
	int destinationIndex = 0;
	int destLen = totalContentLength;
	
	NSMutableData *td = [NSMutableData data];
	char uncomArray[0x8000];
	for (NSData *data in zippedContentList) {
		int len = [data length];
		// NSLog(@"data len = %d",len);
		uLongf unlen = 0x8000;
		char *buf = (char *)[data bytes];
		uncompress((Bytef *)uncomArray, &unlen, (Bytef *)buf, len);
		[td appendBytes:uncomArray length:unlen];
		destinationIndex += unlen;
		buf = nil;
	}
	
	[zippedContentList removeAllObjects];
	
	//char destinationArray[totalContentLength];
	//[td getBytes:destinationArray length:totalContentLength];
	NSString *st;
	NSInteger cc = [chaptersOffset count];
	for (int i = 0; i < cc; i++) {
		st = [chaptersOffset objectAtIndex:i];
		int index = [st intValue];
		
		int count = 0;
		if (i < (cc - 1)) {
			st = [chaptersOffset objectAtIndex:(i + 1)];
			int qq = [st intValue];
			count = qq - index;
		} else {
			count = destLen - index;
		}
		NSString *text1 = nil;
		NSData *sub = [td subdataWithRange:NSMakeRange(index, count)];
		text1 = [[[NSString alloc] initWithData:sub encoding:NSUTF16LittleEndianStringEncoding] autorelease];
		
		Chapter *ch = (Chapter *)[bk.bookChapters objectAtIndex:i];
		ch.content = [text1 stringByReplacingOccurrencesOfString:@"\u2029" withString:@"\r\n"];
	}
	
}

- (Chapter *)getChapter:(NSInteger)index{
	return nil;
}

#pragma mark -
#pragma mark MemoryManage

- (void)dealloc{
	[chaptersOffset release];
	[zippedContentList release];
	[totalImageList release];
	[super dealloc];
}

@end
